home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / ed.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  42KB  |  2,160 lines

  1. /* Copyright 1987 Brian Beattie Rights Reserved.
  2.  *
  3.  * Permission to copy and/or distribute granted under the
  4.  * following conditions:
  5.  *
  6.  * 1). No charge may be made other than resonable charges
  7.  *    for reproduction.
  8.  *
  9.  * 2). This notice must remain intact.
  10.  *
  11.  * 3). No further restrictions may be added.
  12.  *
  13.  */
  14.  
  15. /*    This program used to be in many little pieces, with this makefile:
  16. .SUFFIXES:    .c .s
  17.  
  18. CFLAGS = -F
  19.  
  20. OBJS =    append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\
  21.   doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
  22.   getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s join.s maksub.s\
  23.   move.s optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
  24.   unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s system.s
  25.  
  26. ed:    $(OBJS)
  27.   cc -T. -i -o ed $(OBJS)
  28. */
  29.  
  30. #include <sys/types.h>
  31. #include <signal.h>
  32. #include <stdio.h>
  33.  
  34. /****************************/
  35.  
  36. /*    tools.h    */
  37. /*
  38.  *    #defines for non-printing ASCII characters
  39.  */
  40.  
  41. #define NUL    0x00        /* ^@ */
  42. #define EOS    0x00        /* end of string */
  43. #define SOH    0x01        /* ^A */
  44. #define STX    0x02        /* ^B */
  45. #define ETX    0x03        /* ^C */
  46. #define EOT    0x04        /* ^D */
  47. #define ENQ    0x05        /* ^E */
  48. #define ACK    0x06        /* ^F */
  49. #define BEL    0x07        /* ^G */
  50. #define BS    0x08        /* ^H */
  51. #define HT    0x09        /* ^I */
  52. #define LF    0x0a        /* ^J */
  53. #define NL    '\n'
  54. #define VT    0x0b        /* ^K */
  55. #define FF    0x0c        /* ^L */
  56. #define CR    0x0d        /* ^M */
  57. #define SO    0x0e        /* ^N */
  58. #define SI    0x0f        /* ^O */
  59. #define DLE    0x10        /* ^P */
  60. #define DC1    0x11        /* ^Q */
  61. #define DC2    0x12        /* ^R */
  62. #define DC3    0x13        /* ^S */
  63. #define DC4    0x14        /* ^T */
  64. #define NAK    0x15        /* ^U */
  65. #define SYN    0x16        /* ^V */
  66. #define ETB    0x17        /* ^W */
  67. #define CAN    0x18        /* ^X */
  68. #define EM    0x19        /* ^Y */
  69. #define SUB    0x1a        /* ^Z */
  70. #define ESC    0x1b        /* ^[ */
  71. #define FS    0x1c        /* ^\ */
  72. #define GS    0x1d        /* ^] */
  73. #define RS    0x1e        /* ^^ */
  74. #define US    0x1f        /* ^_ */
  75. #define SP    0x20        /* space */
  76. #define DEL    0x7f        /* DEL */
  77.  
  78.  
  79. #define TRUE    1
  80. #define FALSE    0
  81. #define ERR    -2
  82.  
  83.  
  84. /*    Definitions of meta-characters used in pattern matching
  85.  *    routines.  LITCHAR & NCCL are only used as token identifiers;
  86.  *    all the others are also both token identifier and actual symbol
  87.  *    used in the regular expression.
  88.  */
  89.  
  90.  
  91. #define BOL    '^'
  92. #define EOL    '$'
  93. #define ANY    '.'
  94. #define LITCHAR    'L'
  95. #define    ESCAPE    '\\'
  96. #define CCL    '['        /* Character class: [...] */
  97. #define CCLEND    ']'
  98. #define NEGATE    '~'
  99. #define NCCL    '!'        /* Negative character class [^...] */
  100. #define CLOSURE    '*'
  101. #define OR_SYM    '|'
  102. #define DITTO    '&'
  103. #define OPEN    '('
  104. #define CLOSE    ')'
  105.  
  106. /* Largest permitted size for an expanded character class.  (i.e. the class
  107.  * [a-z] will expand into 26 symbols; [a-z0-9] will expand into 36.)
  108.  */
  109. #define CLS_SIZE    128
  110.  
  111. /*
  112.  *    Tokens are used to hold pattern templates. (see makepat())
  113.  */
  114. typedef char BITMAP;
  115.  
  116. typedef struct token {
  117.   char tok;
  118.   char lchar;
  119.   BITMAP *bitmap;
  120.   struct token *next;
  121. } TOKEN;
  122.  
  123. #define TOKSIZE sizeof (TOKEN)
  124.  
  125. /*
  126.  *    An absolute maximun for strings.
  127.  */
  128.  
  129. #define MAXSTR    132        /* Maximum numbers of characters in a line */
  130.  
  131.  
  132. extern char *matchs();
  133. extern char *amatch();
  134. extern char *in_string();
  135. extern TOKEN *getpat();
  136. extern int esc();
  137. extern char *dodash();
  138. extern TOKEN *makepat();
  139. extern int unmakepat();
  140. extern int insert();
  141. extern int delete();
  142. extern int isalphanum();
  143. extern char *stoupper();
  144. extern int pr_tok();
  145. extern int pr_line();
  146. extern BITMAP *makebitmap();
  147. void set_buf();
  148.  
  149. /* Macros */
  150. #define max(a,b)    ((a>b)?a:b)
  151. #define min(a,b)    ((a<b)?a:b)
  152. #define toupper(c)    (c>='a'&&c<='z'?c-32:c)
  153.  
  154. /*    ed.h    */
  155. #define FATAL    (ERR-1)
  156. struct line {
  157.   int l_stat;            /* empty, mark */
  158.   struct line *l_prev;
  159.   struct line *l_next;
  160.   char l_buff[1];
  161. };
  162.  
  163. typedef struct line LINE;
  164.  
  165. #define LINFREE    1        /* entry not in use */
  166. #define LGLOB    2        /* line marked global */
  167.  
  168. #define MAXLINE    256        /* max number of chars per line */
  169. #define MAXPAT    256        /* max number of chars per replacement
  170.              * pattern */
  171. #define MAXFNAME 256        /* max file name size */
  172.  
  173. extern LINE line0;
  174. extern int curln, lastln, line1, line2, nlines;
  175. extern int nflg;        /* print line number flag */
  176. extern int lflg;        /* print line in verbose mode */
  177. extern char *inptr;        /* tty input buffer */
  178. extern char linbuf[], *linptr;    /* current line */
  179. extern int truncflg;        /* truncate long line flag */
  180. extern int eightbit;        /* save eighth bit */
  181. extern int nonascii;        /* count of non-ascii chars read */
  182. extern int nullchar;        /* count of null chars read */
  183. extern int truncated;        /* count of lines truncated */
  184. extern int fchanged;        /* file changed */
  185.  
  186. #define nextln(l)    ((l)+1 > lastln ? 0 : (l)+1)
  187. #define prevln(l)    ((l)-1 < 0 ? lastln : (l)-1)
  188.  
  189. extern char *getfn();
  190. extern LINE *getptr();
  191. extern char *gettxt();
  192. extern char *maksub();
  193. extern TOKEN *optpat();
  194.  
  195. extern char *catsub();
  196.  
  197. extern char *strcpy(), *strcat();
  198. extern char *malloc();
  199.  
  200. /*    amatch.c    */
  201. /* #include <stdio.h> */
  202. /* #include "tools.h" */
  203.  
  204. /*     Scans throught the pattern template looking for a match
  205.  * with lin.  Each element of lin is compared with the template
  206.  * until either a mis-match is found or the end of the template
  207.  * is reached.  In the former case a 0 is returned; in the latter,
  208.  * a pointer into lin (pointing to the character following the
  209.  * matched pattern) is returned.
  210.  *
  211.  *    "lin"    is a pointer to the line being searched.
  212.  *    "pat"    is a pointer to a template made by makepat().
  213.  *    "boln"    is a pointer into "lin" which points at the
  214.  *            character at the beginning of the line.
  215.  */
  216.  
  217. char *paropen[9], *parclose[9];
  218. int between, parnum;
  219. static char *match();
  220.  
  221. char *amatch(lin, pat, boln)
  222. char *lin;
  223. TOKEN *pat;
  224. char *boln;
  225. {
  226.   between = 0;
  227.   parnum = 0;
  228.  
  229.   lin = match(lin, pat, boln);
  230.  
  231.   if (between) return 0;
  232.  
  233.   while (parnum < 9) {
  234.     paropen[parnum] = parclose[parnum] = "";
  235.     parnum++;
  236.   }
  237.   return lin;
  238. }
  239.  
  240. static char *match(lin, pat, boln)
  241. char *lin;
  242. TOKEN *pat;
  243. char *boln;
  244. {
  245.   register char *bocl, *rval, *strstart;
  246.  
  247.   if (pat == 0) return 0;
  248.  
  249.   strstart = lin;
  250.  
  251.   while (pat) {
  252.     if (pat->tok == CLOSURE && pat->next) {
  253.         /* Process a closure: first skip over the closure
  254.          * token to the object to be repeated.  This object
  255.          * can be a character class. */
  256.  
  257.         pat = pat->next;
  258.  
  259.         /* Now match as many occurrences of the closure
  260.          * pattern as possible. */
  261.         bocl = lin;
  262.  
  263.         while (*lin && omatch(&lin, pat, boln));
  264.  
  265.         /* 'Lin' now points to the character that made made
  266.          * us fail.  Now go on to process the rest of the
  267.          * string.  A problem here is a character following
  268.          * the closure which could have been in the closure.
  269.          * For example, in the pattern "[a-z]*t" (which
  270.          * matches any lower-case word ending in a t), the
  271.          * final 't' will be sucked up in the while loop.
  272.          * So, if the match fails, we back up a notch and try
  273.          * to match the rest of the string again, repeating
  274.          * this process recursively until we get back to the
  275.          * beginning of the closure.  The recursion goes, at
  276.          * most two levels deep. */
  277.  
  278.         if (pat = pat->next) {
  279.             int savbtwn = between;
  280.             int savprnm = parnum;
  281.  
  282.             while (bocl <= lin) {
  283.                 if (rval = match(lin, pat, boln)) {
  284.                     /* Success */
  285.                     return(rval);
  286.                 } else {
  287.                     --lin;
  288.                     between = savbtwn;
  289.                     parnum = savprnm;
  290.                 }
  291.             }
  292.             return(0);    /* match failed */
  293.         }
  294.     } else if (pat->tok == OPEN) {
  295.         if (between || parnum >= 9) return 0;
  296.         paropen[parnum] = lin;
  297.         between = 1;
  298.         pat = pat->next;
  299.     } else if (pat->tok == CLOSE) {
  300.         if (!between) return 0;
  301.         parclose[parnum++] = lin;
  302.         between = 0;
  303.         pat = pat->next;
  304.     } else if (omatch(&lin, pat, boln)) {
  305.         pat = pat->next;
  306.     } else {
  307.         return(0);
  308.     }
  309.   }
  310.  
  311.   /* Note that omatch() advances lin to point at the next character to
  312.    * be matched.  Consequently, when we reach the end of the template,
  313.    * lin will be pointing at the character following the last character
  314.    * matched.  The exceptions are templates containing only a BOLN or
  315.    * EOLN token.  In these cases omatch doesn't advance.
  316.    * 
  317.    * A philosophical point should be mentioned here.  Is $ a position or a
  318.    * character? (i.e. does $ mean the EOL character itself or does it
  319.    * mean the character at the end of the line.)  I decided here to
  320.    * make it mean the former, in order to make the behavior of match()
  321.    * consistent.